#include "ds18b20.h"
#include <iom128.h>
#include <inavr.h>
#include <iomacro.h>
#include <intrinsics.h>
#include "config.h"
#include "uart.h"
#include "bitop.h"

//--------------------------
#if 1

#define DQ        (1<<port_num)
#define DQ_OUT    (DDRC |= DQ)
#define DQ_IN     (DDRC &= ~DQ)
#define DQ_HIGH   (PORTC |= DQ)
#define DQ_LOW    (PORTC &= ~DQ)
#define GET_BIT   (PINC & DQ )

u08 w1_reset(u08 port_num)
{
	u08 err = ERR_NO_ERR;
	u08 err1 = ERR_NO_ERR;
	u08 err2 = ERR_NO_ERR;

	__disable_interrupt ();

	DQ_OUT;       // direction for output          
	DQ_LOW;       // drives the DQ low 
	delayus(600); // delay for 480 us
    //DQ_HIGH;

	DQ_IN; // direction for input
    DQ_HIGH;
	delayus(66); // delay for 70 us
	//delayus(50);
	err1 = GET_BIT; // get reply

	delayus(600-66); // delay for 410 us

	if(GET_BIT==0)
		err2 = 1;

	__enable_interrupt ();

	if(err1||err2)
	{
		err =1;
		//F(("err1=%d err2=%d\r\n",err1,err2));   
	}

	return err;
}
void w1_bit_wr(u08 port_num,u08 bit)
{
	__disable_interrupt ();
	DQ_OUT; // direction for output
	if (bit) // write '1' bit
	{
		DQ_LOW; // drives DQ low
		delayus(6); // low for 6 us
		DQ_HIGH; // releases the bus
		delayus(64); // high for 64 us
	}
	else  // write '0' bit 
	{ 
		DQ_LOW;
		delayus(60); // low for 60 us
		DQ_HIGH; // releases the bus
		delayus(10); // high for 10 us 
	}
	__enable_interrupt ();
} 

void w1_byte_wr(u08 port_num,u08 data)
{
	u08 loop;
	// Loop to write each bit in the byte, LS-bit first
	for (loop=0;loop<8;loop++)
	{
		w1_bit_wr(port_num,data & 0x01);
		data >>= 1; // shift the data for the next bit
	}
} 

u08 w1_bit_rd(u08 port_num)
{
	u08 result =0;
	__disable_interrupt ();
	DQ_OUT;
	DQ_LOW;
	delayus(6); // low for 6 us
	DQ_HIGH; // releases the bus
    //DQ_HIGH; // releases the bus
	DQ_IN;
    DQ_HIGH; // releases the bus
    delayus(14); // high for 9 us

	if(GET_BIT)
		result=1; 

    delayus(50); // delay for 55 us
	__enable_interrupt ();
	return result;
}

u08 w1_byte_rd(u08 port_num)
{
	u08 loop, result=0;
	for (loop=0;loop<8;loop++)
	{
		// shift the result to get it ready for the next bit
		result >>=1;
		// if the result is '1', then set MS bit
		if (w1_bit_rd(port_num)) 
			result |= 0x80;
	}
	return result; 
}
u08 w1_rom_search( u08 port_num,u08 diff, u08  *id )
{
	u08 i, j, next_diff;
	u08 b;
	u08 err = 0;
	u08 try_cnt =3;

	while(try_cnt--)
	{
		err = w1_reset(port_num);
		if(err == ERR_NO_ERR)
			break;
		delayms(10);
	}    
	if(err)
		return PRESENCE_ERR;		  // error, no device found

	w1_byte_wr( port_num,SEARCH_ROM );	  // ROM search command
	next_diff = LAST_DEVICE;				// unchanged on last device
	i = 8 * 8;								// 8 bytes
	do
	{
		j = 8;								// 8 bits
		do
		{
			b = w1_bit_rd( port_num);	// read bit
			if( w1_bit_rd( port_num) ) 	// read complement bit
			{
				if( b )						// 11
					return DATA_ERR;		// data error
			}
			else
			{
				if( !b ) 					// 00 = 2 devices
				{
					if( diff > i ||((*id & 1) && diff != i) )
					{
						b = 1;				// now 1
						next_diff = i;		// next pass 0
					}
				}
			}
			w1_bit_wr( port_num,b );     	// write bit
			*id >>= 1;
			if( b )							// store bit
				*id |= 0x80;
			i--;
		}
		while( --j );
		id++;								// next byte
	}
	while( i );

	return next_diff;						// to continue search
}

//---------------------------
#else
u08 w1_reset(u08 port_num)
{
	u08 err;

	W1_DDR |= 1<<port_num;
	W1_OUT &= ~(1<<port_num);
	delayus( 480 );						// 480 us
	__disable_interrupt ();

	//W1_OUT |=(1<<port_num);
	W1_DDR &= ~(1<<port_num);
	delayus( 66 );
	err = W1_IN & (1<<port_num);			// no presence detect
	__enable_interrupt ();
	delayus( 480-66  );


	F(("err1=%d\r\n",err));

	if( (W1_IN & (1<<port_num)) == 0 )		// short circuit
		err = 1;
	F(("err2=%d\r\n",err));
	return err;
}

static u08 w1_bit_io( u08 port_num,u08 b )
{
	__disable_interrupt ();
	W1_DDR |= 1<<port_num;
	delayus( 1 );
	if( b )
		W1_DDR &= ~(1<<port_num);
	delayus( 15 - 1 );
	if( (W1_IN & (1<<port_num)) == 0 )
		b = 0;
	delayus( 60 - 15 );
	W1_DDR &= ~(1<<port_num);
	__enable_interrupt ();
	return b;
}

u08 w1_byte_wr( u08 port_num,u08 b )
{
	u08 i = 8, j;
	do
	{
		j = w1_bit_io(port_num, b & 1 );
		b >>= 1;
		if( j )
			b |= 0x80;
	}
	while( --i );
	return b;
}

u08 w1_byte_rd( u08 port_num )
{
	return w1_byte_wr( port_num,0xFF );
}



u08 w1_rom_search( u08 port_num,u08 diff, u08  *id )
{
	u08 i, j, next_diff;
	u08 b;

	if( w1_reset(port_num) )
		return PRESENCE_ERR;				// error, no device found
	w1_byte_wr( port_num,SEARCH_ROM );		// ROM search command
	next_diff = LAST_DEVICE;				// unchanged on last device
	i = 8 * 8;								// 8 bytes
	do
	{
		j = 8;								// 8 bits
		do
		{
			b = w1_bit_io( port_num,1 );	// read bit
			if( w1_bit_io( port_num,1 ) ) 	// read complement bit
			{
				if( b )						// 11
					return DATA_ERR;		// data error
			}
			else
			{
				if( !b ) 					// 00 = 2 devices
				{
					if( diff > i ||((*id & 1) && diff != i) )
					{
						b = 1;				// now 1
						next_diff = i;		// next pass 0
					}
				}
			}
			w1_bit_io( port_num,b );     	// write bit
			*id >>= 1;
			if( b )							// store bit
				*id |= 0x80;
			i--;
		}
		while( --j );
		id++;								// next byte
	}
	while( i );

	return next_diff;						// to continue search
}

#endif


